#pragma once

#include <cstdint>
#include <vector>
#include <string>
#include <memory>
#include <cstring>

namespace file_server
{
    namespace protocol
    {

        /**
         * @brief 消息类型枚举
         */
        enum class MessageType : uint16_t
        {
            // 认证相关 (1-99)
            AUTH_REGISTER_REQ = 1,
            AUTH_REGISTER_RESP = 2,
            AUTH_LOGIN_REQ = 3,
            AUTH_LOGIN_RESP = 4,
            AUTH_LOGOUT_REQ = 5,
            AUTH_LOGOUT_RESP = 6,

            // 文件相关 (100-199)
            FILE_UPLOAD_REQ = 100,
            FILE_UPLOAD_RESP = 101,
            FILE_DOWNLOAD_REQ = 102,
            FILE_DOWNLOAD_RESP = 103,
            FILE_DELETE_REQ = 104,
            FILE_DELETE_RESP = 105,
            FILE_LIST_REQ = 106,
            FILE_LIST_RESP = 107,
            FILE_INFO_REQ = 108,
            FILE_INFO_RESP = 109,

            // 分块上传相关 (200-299)
            CHUNK_UPLOAD_INIT_REQ = 200,
            CHUNK_UPLOAD_INIT_RESP = 201,
            CHUNK_UPLOAD_REQ = 202,
            CHUNK_UPLOAD_RESP = 203,
            CHUNK_UPLOAD_COMPLETE_REQ = 204,
            CHUNK_UPLOAD_COMPLETE_RESP = 205,

            // 通知相关 (300-399)
            NOTIFICATION_PUSH = 300,

            // 心跳 (400-499)
            HEARTBEAT_REQ = 400,
            HEARTBEAT_RESP = 401,

            // 错误 (500-599)
            ERROR_RESP = 500,
        };

/**
 * @brief 数据包头部结构
 *
 * 协议格式: [Header(8字节)][Body(N字节)]
 * Header: [Length(4B)][Type(2B)][Reserved(2B)]
 */
#pragma pack(push, 1)
        struct PacketHeader
        {
            uint32_t length;   // 包体长度(不包含Header)
            uint16_t type;     // 消息类型
            uint16_t reserved; // 预留字段(可用于版本号、压缩标志等)

            PacketHeader() : length(0), type(0), reserved(0) {}
            PacketHeader(uint32_t len, MessageType msg_type)
                : length(len), type(static_cast<uint16_t>(msg_type)), reserved(0) {}
        };
#pragma pack(pop)

        static_assert(sizeof(PacketHeader) == 8, "PacketHeader size must be 8 bytes");

        /**
         * @brief 数据包类
         */
        class Packet
        {
        public:
            Packet() = default;
            explicit Packet(MessageType type) : header_(0, type) {}
            Packet(MessageType type, const std::vector<uint8_t> &body)
                : header_(body.size(), type), body_(body) {}
            Packet(MessageType type, std::vector<uint8_t> &&body)
                : header_(body.size(), type), body_(std::move(body)) {}

            /**
             * @brief 获取消息类型
             */
            MessageType GetType() const
            {
                return static_cast<MessageType>(header_.type);
            }

            /**
             * @brief 设置消息类型
             */
            void SetType(MessageType type)
            {
                header_.type = static_cast<uint16_t>(type);
            }

            /**
             * @brief 获取包体长度
             */
            uint32_t GetBodyLength() const
            {
                return header_.length;
            }

            /**
             * @brief 获取包体数据
             */
            const std::vector<uint8_t> &GetBody() const
            {
                return body_;
            }

            /**
             * @brief 设置包体数据
             */
            void SetBody(const std::vector<uint8_t> &body)
            {
                body_ = body;
                header_.length = body_.size();
            }

            void SetBody(std::vector<uint8_t> &&body)
            {
                body_ = std::move(body);
                header_.length = body_.size();
            }

            /**
             * @brief 获取包体字符串(用于JSON等文本协议)
             */
            std::string GetBodyString() const
            {
                return std::string(body_.begin(), body_.end());
            }

            /**
             * @brief 设置包体字符串
             */
            void SetBodyString(const std::string &str)
            {
                body_.assign(str.begin(), str.end());
                header_.length = body_.size();
            }

            /**
             * @brief 序列化为字节流 [Header][Body]
             */
            std::vector<uint8_t> Serialize() const
            {
                std::vector<uint8_t> buffer;
                buffer.reserve(sizeof(PacketHeader) + body_.size());

                // 写入Header
                const uint8_t *header_ptr = reinterpret_cast<const uint8_t *>(&header_);
                buffer.insert(buffer.end(), header_ptr, header_ptr + sizeof(PacketHeader));

                // 写入Body
                buffer.insert(buffer.end(), body_.begin(), body_.end());

                return buffer;
            }

            /**
             * @brief 从字节流反序列化
             * @param data 字节流
             * @param size 字节流长度
             * @return 是否成功
             */
            bool Deserialize(const uint8_t *data, size_t size)
            {
                if (size < sizeof(PacketHeader))
                {
                    return false;
                }

                // 读取Header

                std::copy(data, data + sizeof(PacketHeader), &header_);

                // 检查长度
                if (size < sizeof(PacketHeader) + header_.length)
                {
                    return false;
                }

                // 读取Body
                body_.assign(data + sizeof(PacketHeader),
                             data + sizeof(PacketHeader) + header_.length);

                return true;
            }

            /**
             * @brief 获取数据包总长度
             */
            size_t GetTotalLength() const
            {
                return sizeof(PacketHeader) + body_.size();
            }

            /**
             * @brief 清空数据包
             */
            void Clear()
            {
                header_ = PacketHeader();
                body_.clear();
            }

        private:
            PacketHeader header_;
            std::vector<uint8_t> body_;
        };

        /**
         * @brief 数据包编解码器
         */
        class PacketCodec
        {
        public:
            /**
             * @brief 编码数据包
             */
            static std::vector<uint8_t> Encode(const Packet &packet)
            {
                return packet.Serialize();
            }

            /**
             * @brief 解码数据包
             * @param data 字节流
             * @param size 字节流长度
             * @param packet 输出数据包
             * @return 是否成功
             */
            static bool Decode(const uint8_t *data, size_t size, Packet &packet)
            {
                return packet.Deserialize(data, size);
            }

            /**
             * @brief 从缓冲区中尝试解析一个完整的数据包
             * @param buffer 缓冲区
             * @param packet 输出数据包
             * @return 已消费的字节数,0表示数据不完整,-1表示解析错误
             */
            static int TryDecode(const std::vector<uint8_t> &buffer, Packet &packet)
            {
                // 至少需要Header
                if (buffer.size() < sizeof(PacketHeader))
                {
                    return 0; // 数据不完整
                }

                // 读取Header
                PacketHeader header;
                std::memcpy(&header, buffer.data(), sizeof(PacketHeader));

                // 检查长度合法性(防止恶意攻击)
                const uint32_t MAX_PACKET_SIZE = 100 * 1024 * 1024; // 100MB
                if (header.length > MAX_PACKET_SIZE)
                {
                    return -1; // 非法数据包
                }

                // 检查是否接收完整
                size_t total_size = sizeof(PacketHeader) + header.length;
                if (buffer.size() < total_size)
                {
                    return 0; // 数据不完整
                }

                // 解析数据包
                if (!packet.Deserialize(buffer.data(), total_size))
                {
                    return -1; // 解析失败
                }

                return static_cast<int>(total_size); // 返回已消费字节数
            }
        };

        /**
         * @brief 消息类型转字符串(用于日志)
         */
        inline const char *MessageTypeToString(MessageType type)
        {
            switch (type)
            {
            case MessageType::AUTH_REGISTER_REQ:
                return "AUTH_REGISTER_REQ";
            case MessageType::AUTH_REGISTER_RESP:
                return "AUTH_REGISTER_RESP";
            case MessageType::AUTH_LOGIN_REQ:
                return "AUTH_LOGIN_REQ";
            case MessageType::AUTH_LOGIN_RESP:
                return "AUTH_LOGIN_RESP";
            case MessageType::FILE_UPLOAD_REQ:
                return "FILE_UPLOAD_REQ";
            case MessageType::FILE_UPLOAD_RESP:
                return "FILE_UPLOAD_RESP";
            case MessageType::FILE_DOWNLOAD_REQ:
                return "FILE_DOWNLOAD_REQ";
            case MessageType::FILE_DOWNLOAD_RESP:
                return "FILE_DOWNLOAD_RESP";
            case MessageType::CHUNK_UPLOAD_INIT_REQ:
                return "CHUNK_UPLOAD_INIT_REQ";
            case MessageType::CHUNK_UPLOAD_REQ:
                return "CHUNK_UPLOAD_REQ";
            case MessageType::HEARTBEAT_REQ:
                return "HEARTBEAT_REQ";
            case MessageType::HEARTBEAT_RESP:
                return "HEARTBEAT_RESP";
            case MessageType::ERROR_RESP:
                return "ERROR_RESP";
            default:
                return "UNKNOWN";
            }
        }

    } // namespace protocol
} // namespace file_server
